package com.atom.test.opengl

import android.animation.ValueAnimator
import android.graphics.Color
import android.graphics.PixelFormat
import android.opengl.GLES20
import android.opengl.GLES30
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.SurfaceHolder
import android.view.SurfaceView
import com.atom.module.lib.opengles.draw.GlRect
import com.atom.module.lib.opengles.draw.use
import com.atom.module.lib.opengles.egl.EGLConfigAttrs
import com.atom.module.lib.opengles.egl.EGLContextAttrs
import com.atom.module.lib.opengles.egl.EGLHelper
import com.atom.module.lib.opengles.egl.EGLWrapper
import com.atom.module.lib.opengles.shader.*
import com.atom.module.lib.opengles.texture.GlFramebuffer
import com.atom.module.lib.opengles.texture.GlTexture

class FrameActivity : AppCompatActivity() {

    private lateinit var surfaceView: SurfaceView
    private lateinit var eglWrapper: EGLWrapper

    private lateinit var flatProgram: GlSimpleProgram
    private lateinit var textureProgram: GlTextureProgram
    private lateinit var fbo: GlFramebuffer
    private val scene = GlScene()
    private val quad = GlRect()

    private val drawAnimator = ValueAnimator.ofFloat(0F, 1F).also {
        it.addUpdateListener { draw() }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        surfaceView = SurfaceView(this)
        surfaceView.setZOrderOnTop(true)
        surfaceView.holder.setFormat(PixelFormat.RGBA_8888)
        surfaceView.holder.addCallback(object : SurfaceHolder.Callback {
            override fun surfaceCreated(holder: SurfaceHolder) {
                onSurfaceCreated()
            }

            override fun surfaceChanged(
                holder: SurfaceHolder,
                format: Int,
                width: Int,
                height: Int
            ) {
                GLES20.glViewport(0, 0, width, height)
                scene.setViewportSize(width, height)
            }

            override fun surfaceDestroyed(holder: SurfaceHolder) {
                onSurfaceDestroyed()
            }
        })
        setContentView(surfaceView)
    }

    private fun onSurfaceCreated() {
        eglWrapper = EGLHelper.initDisplay()
        eglWrapper.createGLESWithSurface(
            EGLConfigAttrs().version(3).recordableType(false),
            EGLContextAttrs().version(3),
            surfaceView.holder.surface!!
        )
        fbo = GlFramebuffer()
        flatProgram = GlSimpleProgram()
        flatProgram.setColor(Color.GREEN)

        textureProgram = GlTextureProgram(
            TextureVShader.create(), TextureFShaderDefault.create() , GlTexture(GLES30.GL_TEXTURE0, GLES30.GL_TEXTURE_2D, 100, 100)
        )

        drawAnimator.start()
    }

    private fun onSurfaceDestroyed() {
        drawAnimator.cancel()
        flatProgram.release()
        textureProgram.release()
        eglWrapper.release()
        fbo.release()
    }

    private fun draw() {
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT)
        fbo.attach(textureProgram.glTexture)
        fbo.use {
            scene.setViewportSize(scene.viewportWidth/2 ,scene.viewportHeight/2 )
            scene.draw(flatProgram, quad)
        }
        scene.setViewportSize(-1 , -1)
        scene.draw(textureProgram, quad)
        // Publish.
        eglWrapper.swapBuffers()
    }


    override fun onDestroy() {
        onSurfaceDestroyed()
        super.onDestroy()
    }
}
